import {
  Id,
  accessify,
  beSignature,
  soStatements
} from './entry'

import {
  Acceptor,
  Func,
  Method,
  Overload,
} from '../ast/types'

import sign, {
  isKeyword,
  isInfix,
} from '../ast/sign'

const
  IDENT   = sign.ident,
  BITNOT  = sign['~'],
  DOTDOT  = sign['..'],
  L       = sign['[']

function overloading (s) {
  let sign = s.right() || s.unexpected()
  if (
    isInfix(sign) && !isKeyword(sign)
    || sign === DOTDOT
    || sign === BITNOT
    || sign === L && s.rune === 0x78 // [x]
    && s.drop().rune === 0x5D && s.drop()
  )
    return new Overload(s.text())
      .start(s.start).end(s.end)

  s.unexpected()
}

function beAcceptor (model, action) {
  return new Acceptor(model, action)
    .start(model.loc.start).end(action.loc.end)
}

export default function (s) {
  let
    x, start  = s.start,
    access = accessify(s.text()),
    id  = s.sps().beId(),
    node = s.dot()
      && new Method(access, beAcceptor(id, s.asId()), beSignature(s))
      || s.at()
      && new Method(access, beAcceptor(id, overloading(s)), beSignature(s))
      || new Func(access, id, beSignature(s)),
    sign = s.soMore()

  node.start(start)

  if (sign)
    return soStatements(s, node, sign)

  return node.end(node.mold.loc.end)
}
